package com.example.mvvmtemplate.utli.video;

import android.content.Context;
import android.graphics.Color;
import android.net.Uri;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Map;

import tv.danmaku.ijk.media.player.IMediaPlayer;
import tv.danmaku.ijk.media.player.IjkMediaPlayer;

public abstract class BaseVideoPlayer extends FrameLayout {

    public abstract IMediaPlayer createPlayer();

    public Context mContext;
    protected SurfaceView mSurfaceView;

    /**
     * 由ijkplayer提供，用于播放视频，需要给他传入一个surfaceView
     */
    private IMediaPlayer mMediaPlayer = null;

    private boolean mEnableMediaCodec = true;

    private int mWidth;
    private int mHeight;
    /**
     * 是否开启视频比例
     */
    private boolean isOpenProportion = false;

    public BaseVideoPlayer(@NonNull Context context) {
        this(context, null);
    }

    public BaseVideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BaseVideoPlayer(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        mContext = context;
        setBackgroundColor(Color.BLACK);
        createSurfaceView();
    }

    private void createSurfaceView() {
        mSurfaceView = new SurfaceView(mContext);
        mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                setSurfaceViewSize();
            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
                if (mMediaPlayer != null) {
                    mMediaPlayer.setDisplay(surfaceHolder);
                }
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder surfaceHolder) {

            }
        });
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT
                , Gravity.CENTER);

        addView(mSurfaceView, 0, layoutParams);
    }

    public void setPathLoad(String path) throws IOException {
        setPathLoad(path, null);
    }

    public void setPathLoad(String path, Map<String, String> header) throws IOException {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
        }
        if (mSurfaceView.getVisibility() != VISIBLE) {
            mSurfaceView.setVisibility(VISIBLE);
        }
        mMediaPlayer = createPlayer();
        setListener(mMediaPlayer);
        mMediaPlayer.setDisplay(mSurfaceView.getHolder());
        mMediaPlayer.setDataSource(mContext, Uri.parse(path), header);

        mMediaPlayer.prepareAsync();
    }

    private void setListener(IMediaPlayer player) {
        //在视频预处理完成后被调用。此时视频的宽度、高度、宽高比信息已经获取到，此时可调用seekTo让视频从指定位置开始播放。
        player.setOnPreparedListener(iMediaPlayer -> {
            if (onPreparedListener != null) {
                onPreparedListener.onPreparedListener(iMediaPlayer);
            } else {
                iMediaPlayer.start();
            }
        });
        player.setOnCompletionListener(iMediaPlayer -> {
            if (videoCompletionListener != null) {
                videoCompletionListener.onCompletion(iMediaPlayer);
            }
        });
    }

    /**
     * 设置自己的player回调
     */
    public void setOnPreparedListener(OnPreparedListener listener) {
        onPreparedListener = listener;
    }

    /**
     * 设置播放完毕回调
     */
    public void setVideoCompletionListener(VideoCompletionListener videoCompletionListener) {
        this.videoCompletionListener = videoCompletionListener;
    }

    private OnPreparedListener onPreparedListener;

    public interface OnPreparedListener {
        void onPreparedListener(IMediaPlayer iMediaPlayer);
    }

    private VideoCompletionListener videoCompletionListener;

    public interface VideoCompletionListener {
        void onCompletion(IMediaPlayer iMediaPlayer);
    }

    public void setEnableMediaCodec(IjkMediaPlayer ijkMediaPlayer) {
        int value = mEnableMediaCodec ? 1 : 0;
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", value);//开启硬解码
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", value);
        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", value);
    }

    /**
     * 设置是否开启硬解码
     */
    public void setEnableMediaCodec(boolean isEnable) {
        mEnableMediaCodec = isEnable;
    }

    public IMediaPlayer getIMediaPlayer() {
        return mMediaPlayer;
    }

    public void start() {
        if (mMediaPlayer != null) {
            mMediaPlayer.start();
        }
    }

    /**
     * 释放
     */
    public void release() {
        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    public void releaseHide() {
        release();
        mSurfaceView.setVisibility(INVISIBLE);
    }

    public void pause() {
        if (mMediaPlayer != null) {
            mMediaPlayer.pause();
        }
    }

    public void stop() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
        }
    }

    /**
     * 重置
     */
    public void reset() {
        if (mMediaPlayer != null) {
            mMediaPlayer.reset();
        }
    }

    public long getDuration() {
        if (mMediaPlayer != null) {
            return mMediaPlayer.getDuration();
        } else {
            return 0;
        }
    }

    public long getCurrentPosition() {
        if (mMediaPlayer != null) {
            return mMediaPlayer.getCurrentPosition();
        } else {
            return 0;
        }
    }

    public void seekTo(long l) {
        if (mMediaPlayer != null) {
            mMediaPlayer.seekTo(l);
        }
    }

    public boolean isPlaying() {
        if (mMediaPlayer != null) {
            return mMediaPlayer.isPlaying();
        }
        return false;
    }

    public void setVolume(float var1, float var2) {
        if (mMediaPlayer != null) {
            mMediaPlayer.setVolume(var1, var2);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int mWidthMode = MeasureSpec.getMode(widthMeasureSpec);
        int mWidthSize = MeasureSpec.getSize(widthMeasureSpec);

        int mHeightMode = MeasureSpec.getMode(heightMeasureSpec);
        int mHeightSize = MeasureSpec.getSize(heightMeasureSpec);

        if (isOpenProportion) {
            float proportion1 = getHeightVideoRatio();
            float proportion2 = mHeightSize * 1f / mWidthSize;
            if (proportion1 > proportion2) {
                mHeight = mHeightSize;

                if (mWidthMode == MeasureSpec.EXACTLY) {
                    mWidth = mWidthSize;
                } else {
                    int maxWidth = (int) (mHeight * proportion1 + .5);
                    mWidth = getPaddingStart() + maxWidth + getPaddingEnd();
                    if (mWidthMode == MeasureSpec.AT_MOST) {
                        mWidth = Math.min(mWidth, mWidthSize);
                    }
                }
            } else {
                mWidth = mWidthSize;

                if (mHeightMode == MeasureSpec.EXACTLY) {
                    mHeight = mHeightSize;
                } else {
                    int maxHeight = (int) (mWidth * proportion1 + .5);
                    mHeight = getPaddingTop() + maxHeight + getPaddingBottom();
                    if (mHeightMode == MeasureSpec.AT_MOST) {
                        mHeight = Math.min(mHeight, mHeightSize);
                    }
                }
            }
        } else {
            if (mWidthMode == MeasureSpec.EXACTLY) {
                mWidth = mWidthSize;
            } else {
                mWidth = getPaddingStart() + getPaddingEnd();
                if (mWidthMode == MeasureSpec.AT_MOST) {
                    mWidth = Math.min(mWidth, mWidthSize);
                }
            }

            if (mHeightMode == MeasureSpec.EXACTLY) {
                mHeight = mHeightSize;
            } else {
                mHeight = getPaddingTop() + getPaddingBottom();
                if (mHeightMode == MeasureSpec.AT_MOST) {
                    mHeight = Math.min(mHeight, mHeightSize);
                }
            }
        }

        setMeasuredDimension(mWidth, mHeight);
    }

    private float getHeightVideoRatio() {
        if (proportion == PROPORTION_4_3) {
            return 3 / 4f;
        } else if (proportion == PROPORTION_18_9) {
            return 9 / 18f;
        } else if (proportion == PROPORTION_2_39) {
            return 1 / 2.39f;
        } else {
            return 9 / 16f;
        }
    }

    private float getWidthVideoRatio() {
        if (proportion == PROPORTION_4_3) {
            return 4 / 3f;
        } else if (proportion == PROPORTION_18_9) {
            return 18 / 9f;
        } else if (proportion == PROPORTION_2_39) {
            return 2.39f;
        } else {
            return 16 / 9f;
        }
    }

    /**
     * 设置SurfaceView大小
     */
    private void setSurfaceViewSize() {
        if (isOpenProportion) {
            float proportion1 = getHeightVideoRatio();
            float proportion2 = mHeight * 1f / mWidth;
            ViewGroup.LayoutParams layoutParam = mSurfaceView.getLayoutParams();
            if (proportion1 > proportion2) {
                layoutParam.width = (int) (mHeight * getWidthVideoRatio() + .5);
                layoutParam.height = mHeight;
            } else {
                layoutParam.width = mWidth;
                layoutParam.height = (int) (mWidth * proportion1 + .5);
            }
            mSurfaceView.setLayoutParams(layoutParam);
        }
    }

    public static final int PROPORTION_16_9 = 1;
    public static final int PROPORTION_4_3 = 2;
    public static final int PROPORTION_18_9 = 3;
    public static final int PROPORTION_2_39 = 4;

    @IntDef({PROPORTION_16_9, PROPORTION_4_3, PROPORTION_18_9, PROPORTION_2_39})
    @Retention(RetentionPolicy.SOURCE)
    private @interface ProportionType {
    }

    private int proportion = PROPORTION_16_9;

    public int getProportion() {
        return proportion;
    }

    /**
     * 设置初始播放比例
     */
    public void setInitProportion(@ProportionType int proportion) {
        this.proportion = proportion;
    }

    /**
     * 设置视频比例
     */
    public void setProportion(@ProportionType int proportion) {
        this.proportion = proportion;
        setSurfaceViewSize();
    }

    /**
     * 开启视频比例，默认为false
     */
    public void setOpenProportion() {
        isOpenProportion = true;
    }
}
